' *********************************************************************************
' *********************************************************************************
' **
' ** Created By: Jim Dempsey
' ** Created Date: 21-DEC-2011
' **
' **
' ** Revision History:
' **   v1.0 - Basic installation with default MP and DP settings
' **
' **
' ** ToDo's:
' **   - Add error handling
' **   - Consider alternate installation account credentials
' **   - Consider custom schedules/rate limits for sender
' **   - Consider support for custom DP configuration (e.g. boundary group support)
' **   - Consider HTTPS mode for MP and DP roles
' **
' **
' ** Special Thanks To:
' **   - Jon Shi for providing the original script to work from.
' **
' **
' ** Disclaimer:
' **   This script is provided for informational purposes only.
' **   Microsoft and the author make no warranties, express or implied.
' **
' *********************************************************************************
' *********************************************************************************


' *********************************************************************************
' ******  ENTER THE DESIRED VALUES FOR THE USER DEFINED VARIABLES BELOW ***********
' *********************************************************************************
' **
' ** DNSDomainName - FQDN for the domain in which both the primary and secondary sites reside (e.g. contoso.com)
' **
' ** PrimarySiteCode - 3-character site code for an existing primary site that will be the parent of the new secondary site
' ** PrimarySiteServerName - NetBIOS name of the primary site server computer (must match DNS hostname)
' **
' ** SecondarySiteCode - unique 3-character site code for the new secondary site
' ** SecondarySiteServerName - NetBIOS name of the secondary site server computer (must match DNS hostname)
' ** SecondarySiteName - brief description used to identify the new secondary site
' ** SecondarySiteInstallFolder - local drive path on secondary site server where ConfigMgr will be installed (include trailing backslash, e.g. D:\ConfigMgr\)
' **
' ** InstallSQLExpress - flag to determine if SQL Express should be installed or not (0 = Don't Install, 1 = Install)
' ** SQLInstanceName - SQL Server instance to be used for the secondary site database (optional if InstallSQLExpress = 0, ignored if InstallSQLExpress = 1)
' ** SQLDatabaseName - database name to be used for the secondary site database (required if InstallSQLExpress = 0, ignored if InstallSQLExpress = 1)
' ** SQLServicePort - port number to be used for the SQL Server Engine (required if InstallSQLExpress = 1, ignored if InstallSQLExpress = 0)
' ** SSBPort - port number to be used for the SQL Service Broker (required, used for intersite database replication)
' **
' ** AlternateBuildSourcePath - Local drive path on secondary site server or UNC path where the ConfigMgr installation media and prerequisite files can be found (optional - leave blank to push from primary site)
' **
' ** IsProtected - flag to determine if clients can fallback to this site's distribution point when a preferred distribution point is not available (0 = allow fallback, 1 = do not allow fallback)
' **
' *********************************************************************************
' ******  BEGIN: USER DEFINED VARIABLES *******************************************

  DIM DNSDomainName: DNSDomainName = ""					'*Required* (e.g. "contoso.com")

  DIM PrimarySiteCode: PrimarySiteCode = ""				'*Required* (e.g. "PS1")
  DIM PrimarySiteServerName: PrimarySiteServerName = ""			'*Required* (e.g. "priserver")

  DIM SecondarySiteCode: SecondarySiteCode = ""				'*Required* (e.g. "SS1")
  DIM SecondarySiteServerName: SecondarySiteServerName = ""		'*Required* (e.g. "secserver")
  DIM SecondarySiteName: SecondarySiteName = ""				'*Required* (e.g. "My Secondary Site #1")
  DIM SecondarySiteInstallFolder: SecondarySiteInstallFolder = "C:\Program Files\Microsoft Configuration Manager\"	'*Required*

  DIM InstallSQLExpress: InstallSQLExpress = 1				'*Required*
  DIM SQLInstanceName: SQLInstanceName = "CONFIGMGRSEC"			'*Optional*
  DIM SQLDatabaseName: SQLDatabaseName = "CM_" & SecondarySiteCode	'*Required if InstallSQLExpress=0*
  DIM SQLServicePort: SQLServicePort = 1433				'*Required if InstallSQLExpress=1*
  DIM SSBPort: SSBPort = 4022						'*Required*

  DIM AlternateBuildSourcePath: AlternateBuildSourcePath = ""		'*Optional* (e.g. "" or "C:\ConfigMgrSource" or "\\server\share")

  DIM IsProtected: IsProtected = 0					'*Required*

' ******  END: USER DEFINED VARIABLES *********************************************
' *********************************************************************************
' *********************************************************************************

DIM oWMIService 
DIM oSites
DIM oSiteDefinition
DIM oAddress
DIM oSite
DIM sValues 
DIM iBuildNumber
DIM sFullVersion
DIM PriToSecRateLimits
DIM SecToPriRateLimits
DIM Backup 
DIM HourUsage 

Set oWMIService = GetObject("winmgmts:" _ 
    & "{impersonationLevel=impersonate}!\\" & PrimarySiteServerName & "\root\sms\site_" & PrimarySiteCode) 

Set oSites = oWMIService.ExecQuery _
    ("Select * from SMS_Site where SiteCode='" & PrimarySiteCode & "'")

For Each oSite in oSites
    iBuildNumber = oSite.BuildNumber
    sFullVersion = oSite.Version
Next


' ==============================
' Create Site_Definition
' ==============================

SET oSiteDefinition = oWMIService.Get("SMS_SCI_SiteDefinition").Spawninstance_()

oSiteDefinition.FileType = 2
oSiteDefinition.InstallDirectory = SecondarySiteInstallFolder
oSiteDefinition.ItemName = "Site Definition"
oSiteDefinition.ItemType = "Site Definition"
oSiteDefinition.ParentSiteCode = PrimarySiteCode
oSiteDefinition.ServiceAccount = ""
oSiteDefinition.ServiceAccountDomain = ""
oSiteDefinition.ServiceAccountPassword = ""
oSiteDefinition.ServiceExchangeKey = ""
oSiteDefinition.ServicePlaintextAccount = ""
oSiteDefinition.ServicePublicKey = ""
oSiteDefinition.SiteCode = SecondarySiteCode
oSiteDefinition.SiteName = SecondarySiteName
oSiteDefinition.SiteServerDomain = DNSDomainName
oSiteDefinition.SiteServerName = SecondarySiteServerName & "." & DNSDomainName
oSiteDefinition.SiteServerPlatform = "AMD64"
oSiteDefinition.SiteType = 1
oSiteDefinition.SQLAccount = ""
oSiteDefinition.SQLAccountPassword = ""

If InstallSQLExpress = 1 Then
    SQLInstanceName = "CONFIGMGRSEC"
    SQLDatabaseName = "CM_" & SecondarySiteCode
End If

If SQLInstanceName = "" Then
    oSiteDefinition.SQLDatabaseName = SQLDatabaseName
Else
    oSiteDefinition.SQLDatabaseName = SQLInstanceName & "\" & SQLDatabaseName
End If

oSiteDefinition.SQLPublicKey = ""
oSiteDefinition.SQLServerName = SecondarySiteServerName & "." & DNSDomainName

' Add EmbeddedProperty
AddEmbeddedProperty oWMIService, oSiteDefinition, "Full Version", 0, sFullVersion, ""
AddEmbeddedProperty oWMIService, oSiteDefinition, "LocaleID", 1033, "", ""
AddEmbeddedProperty oWMIService, oSiteDefinition, "IsDiscoverySite", 0, "", ""
AddEmbeddedProperty oWMIService, oSiteDefinition, "Security Mode", 0, "Advanced", ""
AddEmbeddedProperty oWMIService, oSiteDefinition, "Update DNS names", 0, "", ""
AddEmbeddedProperty oWMIService, oSiteDefinition, "ProviderServerName", 0, SecondarySiteServerName, ""
AddEmbeddedProperty oWMIService, oSiteDefinition, "IsProtected", IsProtected, "", ""
AddEmbeddedProperty oWMIService, oSiteDefinition, "InstallSQLExpress", InstallSQLExpress, "", ""
AddEmbeddedProperty oWMIService, oSiteDefinition, "SQLServerFQDN", 0, SecondarySiteServerName & "." & DNSDomainName, ""

If InstallSQLExpress = 1 Then
    AddEmbeddedProperty oWMIService, oSiteDefinition, "SQLServicePort", SQLServicePort, "", ""
End If

AddEmbeddedProperty oWMIService, oSiteDefinition, "SSBPort", SSBPort, "", ""

If AlternateBuildSourcePath <> "" Then
    AddEmbeddedProperty oWMIService, oSiteDefinition, "Setup Source Directory", 0, AlternateBuildSourcePath, ""
    AddEmbeddedProperty oWMIService, oSiteDefinition, "Requested Status", 0, "2", "1002"
Else
    AddEmbeddedProperty oWMIService, oSiteDefinition, "Requested Status", 0, "2", "1001"
End If


' Add EmbeddedPropertyList
sValues = array("SMS")
AddEmbeddedPropertyList oWMIService, oSiteDefinition, "Installed Units", sValues 
sValues = array("")
AddEmbeddedPropertyList oWMIService, oSiteDefinition, "BoundaryGroupIDs", sValues 
sValues = array("")
AddEmbeddedPropertyList oWMIService, oSiteDefinition, "BoundaryGroupFlags", sValues 

oSiteDefinition.put_

WScript.StdOut.WriteLine "Finished creating SiteDefinition."

' ==============================
' Create Return Address
' ==============================

SecToPriRateLimits = array(100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100)

SET oAddress = oWMIService.Get("SMS_SCI_Address").Spawninstance_()
oAddress.AddressPriorityOrder = 0
oAddress.AddressType = "MS_LAN"
oAddress.DesSiteCode = PrimarySiteCode
oAddress.FileType = 2
oAddress.DestinationType = 0
oAddress.SiteCode = SecondarySiteCode
oAddress.UnlimitedRateForAll = TRUE
oAddress.RateLimitingSchedule = SecToPriRateLimits

' Property
AddEmbeddedProperty oWMIService, oAddress, "Connection Point", 0, PrimarySiteServerName & "." & DNSDomainName, "SMS_SITE"
AddEmbeddedProperty oWMIService, oAddress, "LAN Login", 0, "", ""

' UsageSchedule
Backup = array(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)
HourUsage = array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
AddSiteControlDaySchedule oWMIService, oAddress, Backup, HourUsage, FALSE

Backup = array(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)
HourUsage = array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
AddSiteControlDaySchedule oWMIService, oAddress, Backup, HourUsage, FALSE

Backup = array(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)
HourUsage = array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
AddSiteControlDaySchedule oWMIService, oAddress, Backup, HourUsage, FALSE

Backup = array(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)
HourUsage = array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
AddSiteControlDaySchedule oWMIService, oAddress, Backup, HourUsage, FALSE

Backup = array(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)
HourUsage = array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
AddSiteControlDaySchedule oWMIService, oAddress, Backup, HourUsage, FALSE

Backup = array(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)
HourUsage = array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
AddSiteControlDaySchedule oWMIService, oAddress, Backup, HourUsage, FALSE

Backup = array(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)
HourUsage = array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
AddSiteControlDaySchedule oWMIService, oAddress, Backup, HourUsage, FALSE

' Add EmbeddedPropertyList
sValues = array("0", "3", "5")
AddEmbeddedPropertyList oWMIService, oAddress, "Pulse Mode", sValues

oAddress.put_

WScript.StdOut.WriteLine "Finished creating Return Address."

' ==============================
' Create Forward Address
' ==============================

PriToSecRateLimits = array(100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100)

SET oAddress = oWMIService.Get("SMS_SCI_Address").Spawninstance_()
oAddress.AddressPriorityOrder = 0
oAddress.AddressType = "MS_LAN"
oAddress.DesSiteCode = SecondarySiteCode
oAddress.FileType = 2
oAddress.DestinationType = 0
oAddress.SiteCode = PrimarySiteCode
oAddress.UnlimitedRateForAll = TRUE
oAddress.RateLimitingSchedule = PriToSecRateLimits

' Property
AddEmbeddedProperty oWMIService, oAddress, "Connection Point", 0, SecondarySiteServerName & "." & DNSDomainName, "SMS_SITE"
AddEmbeddedProperty oWMIService, oAddress, "LAN Login", 0, "", ""

' DaySchedule
Backup = array(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)
HourUsage = array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
AddSiteControlDaySchedule oWMIService, oAddress, Backup, HourUsage, FALSE

Backup = array(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)
HourUsage = array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
AddSiteControlDaySchedule oWMIService, oAddress, Backup, HourUsage, FALSE

Backup = array(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)
HourUsage = array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
AddSiteControlDaySchedule oWMIService, oAddress, Backup, HourUsage, FALSE

Backup = array(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)
HourUsage = array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
AddSiteControlDaySchedule oWMIService, oAddress, Backup, HourUsage, FALSE

Backup = array(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)
HourUsage = array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
AddSiteControlDaySchedule oWMIService, oAddress, Backup, HourUsage, FALSE

Backup = array(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)
HourUsage = array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
AddSiteControlDaySchedule oWMIService, oAddress, Backup, HourUsage, FALSE

Backup = array(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)
HourUsage = array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
AddSiteControlDaySchedule oWMIService, oAddress, Backup, HourUsage, FALSE

' Add EmbeddedPropertyList
sValues = array("0", "3", "5")
AddEmbeddedPropertyList oWMIService, oAddress, "Pulse Mode", sValues

oAddress.put_

WScript.StdOut.WriteLine "Finished creating Forward Address."

' ==============================
' Create Site
' ==============================
SET oSite = oWMIService.Get("SMS_Site").Spawninstance_()
oSite.SiteCode = SecondarySiteCode
oSite.SiteName = SecondarySiteName
oSite.ServerName = SecondarySiteServerName & "." & DNSDomainName
oSite.BuildNumber = iBuildNumber
oSite.InstallDir = SecondarySiteInstallFolder
oSite.Mode = 0
oSite.ReportingSiteCode = PrimarySiteCode
oSite.Version = sFullVersion
oSite.Type = 1

If AlternateBuildSourcePath = "" Then
    oSite.RequestedStatus = 1001
Else
    oSite.RequestedStatus = 1002
End If

oSite.put_

WScript.StdOut.WriteLine "Finished creating Site."


Sub AddEmbeddedProperty(oWMIService, oSCFObject, sPropertyName, iValue, sValue1, sValue2)
    ' Property does not exist, so create it.
    Dim embeddedProperty
    Set embeddedProperty = oWMIService.Get("SMS_EmbeddedProperty").Spawninstance_()
    embeddedProperty.PropertyName = sPropertyName
    embeddedProperty.Value = iValue
    embeddedProperty.Value1 = sValue1
    embeddedProperty.Value2 = sValue2
      
    ' Add the property to the properties.
    ' If the props array doesn't exist, create it.
    If ISNull (oSCFObject.Props) Then
        oSCFObject.Props = array(embeddedProperty)
    Else   
        ' Grow the array and add the property.
        dim properties
        properties = oSCFObject.Props
        Redim Preserve properties(UBound(properties) + 1)
        Set properties(UBound(properties)) = embeddedProperty
        oSCFObject.Props = properties
    End If 
End Sub

Sub AddEmbeddedPropertyList(oWMIService, oSCFObject, sPropertyListName, sValues)
    ' Property list doesn't exist, so create it.
    Dim embeddedPropertyList
    Set embeddedPropertyList = oWMIService.Get("SMS_EmbeddedPropertyList").Spawninstance_()
    embeddedPropertyList.PropertyListName = sPropertyListName
    embeddedPropertyList.Values = sValues
      
    ' If needed, create the property list array.
    If ISNull (oSCFObject.PropLists) Then
       oSCFObject.PropLists = array(embeddedPropertyList)
    Else
        ' Add property list to existing property lists.
        dim propertyList
        propertyList = oSCFObject.PropLists
        redim preserve propertyList(Ubound (propertyList) +1)
        Set propertyList(Ubound(propertyList)) = embeddedPropertyList
        oSCFObject.Proplists = propertyList
    End If
End Sub          

Sub AddSiteControlDaySchedule(oWMIService, oSCFObject, Backup, HourUsage, update)
    Dim oSchedule
    Set oSchedule = oWMIService.Get("SMS_SiteControlDaySchedule").Spawninstance_()
    oSchedule.Backup = Backup
    oSchedule.HourUsage = HourUsage
    oSchedule.update = update

    If ISNull (oSCFObject.UsageSchedule) Then
        oSCFObject.UsageSchedule = array(oSchedule)
    Else
        ' Grow the array and add the property.
        dim oUsageSchedules
        oUsageSchedules = oSCFObject.UsageSchedule
        Redim Preserve properties(UBound(oUsageSchedules) + 1)
        Set oUsageSchedules(UBound(oUsageSchedules)) = oSchedule
        oSCFObject.UsageSchedule = oUsageSchedules
    End If 
End Sub
